#include "main.h"
#include "assitant.h"
#include "mqtts.h"

typedef enum
{
    Idle,
    Activated,
    Responded,
    Off
} AlertState;

void drive_alert_state();
int recall_alert_signal();
int public_an_alert_signal();
void *_alert_pipe_stream(void *arg, char *data, int len);
void alert_init();
int _fun_alert(int mode);

AlertState _alert_state = Idle;
#define NextTo(s) _alert_state = s
Pipe _alert_in = NULL;
long int _first_alerted_time = 0, _last_recall_time = 0;
int _alert_off_gap = 30000;         // 30s
int _alert_reactivate_gap = 120000; // 120s
void alert_init()
{
    public_a_fun_link_int("alert", (void *)_fun_alert, 1);
}

int _fun_alert(int mode)
{
    if (mode == 1)
    {
        _alert_state = Idle;
        if (!_alert_in)
            _alert_in = new_output_device("alert", NULL, _alert_pipe_stream);

        if (!search_var_in_Lily_ui("alert_gap2"))
        {
            public_a_var_ref("alert_gap2", &_alert_off_gap, 'd');
            public_a_var_ref("alert_gap3", &_alert_reactivate_gap, 'd');
        }
        return 0;
    }
    remove_a_pipe(_alert_in, 'e');
    _alert_in = NULL;
    return 0;
}
void *_alert_pipe_stream(void *arg, char *data, int len)
{
    drive_alert_state();
    return NULL;
}

int public_an_alert_signal()
{
    const char *args[2];
    args[1] = "-t";
    if (cmd_beep(2, (char **)args) < 0)
    {
        outs("error to start buzzer");
    }
    if (!mqtt_client.connected())
        return -1;
    String top = "lily/" + client_id + "/msg";
    time_t now = service_time();
    sprintf(tx, "$alert:%lld", now);
    xouts(tx);
    var ok = mqtt_client.publish(top.c_str(), tx);
    if (!ok)
    {
        mqtt_client.loop();
        ok = mqtt_client.publish(top.c_str(), tx);
        if (!ok)
            return -2;
    }
    return 0;
}

int recall_alert_signal()
{
    cmd_beep(1, NULL);
    if (!mqtt_client.connected())
        return -1;
    String top = "lily/" + client_id + "/msg";
    time_t now = service_time();
    sprintf(tx, "$recall:%lld", now);
    xouts(tx);
    var ok = mqtt_client.publish(top.c_str(), tx);
    if (!ok)
    {
        mqtt_client.loop();
        ok = mqtt_client.publish(top.c_str(), tx);
        if (!ok)
            return -2;
    }
    return 0;
}
void drive_alert_state()
{
    long int now = 0;
    switch (_alert_state)
    {
    case Idle:
        now = millis();
        if (now - _last_recall_time < _alert_reactivate_gap)
            return;
        _first_alerted_time = now;
        NextTo(Activated);
        add_timer_once(public_an_alert_signal, Second(1.5f));
        break;
    case Activated:
        now = millis();
        if (now - _first_alerted_time < _alert_off_gap)
        {
            return;
        }
        // _first_alerted_time = now;
        recall_alert_signal();
        _last_recall_time = now;
        NextTo(Idle);
        break;
    case Responded: // deprecated
        now = millis();
        if (now - _first_alerted_time < _alert_reactivate_gap)
        {
            return;
        }
        NextTo(Idle);
        break;
    default:
        break;
    }
}
#undef NextTo